/*
 * ControlThread.java
 * 
 * last update: 15.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */

package engine;

/**
 * Implements a thread of control which executes concurrently
 */

class ControlThread extends Thread{

	/**
	 * true if the simulation is in course
	 */
	public static volatile boolean doRun;

	/**
	 * the instruction list to be
	 * executed by this thread
	 */
	Instruction ins;

	/**
	 * true if this thread is suspended
	 */
	volatile boolean sleepy;

	/**
	 * counts the active threads
	 * (those witch are not always...)
	 */
	static volatile int activeThreads;

	Object semaphore;

	ControlThread(Instruction ins, ThreadGroup tg){
		super(tg, (Runnable)null);
		this.ins = ins;
		sleepy = false;
	}

	ControlThread(Instruction ins){
		this.ins = ins;
	}

	public void run() {
		try {
			activeThreads ++;
			try {
				while(ins != null) {
					synchronized(xConsole.lock) {
						if (!xConsole.enableExecution()) {
							Time.stopSimulation();
							throw new SimulationStoppedException();
						}
						xConsole.consumeStep();
					}
					ins.execute();
					ins = ins.next();
					//xConsole.debug("coming: " + ins);
				}
				xConsole.debug("Thread " + this + " done.");
			} catch (InterpretTimeException ex) {
				xConsole.dumpStack(ex);
				xConsole.debug("InterpretTimeException caught in ControlThread " + this);
				xConsole.cout(ex.toString());
				Time.stopSimulation();
			}
			ins = null;
			activeThreads--;
			Time.removeThread(this);
		} catch (SimulationStoppedException ex) {
			xConsole.debug(ex.toString() + "  " + this);
		}
	}


	public static void goSleepy()
	throws SimulationStoppedException
	{
		ControlThread th = (ControlThread)Thread.currentThread();
		goSleepy(th);
	}

	public static void goSleepy(Object semaphore)
	throws SimulationStoppedException
	{
		ControlThread th = (ControlThread)Thread.currentThread();
		if (!th.sleepy) {
			synchronized(semaphore) {
				th.sleepy = true;
				th.semaphore = semaphore;
				try {
					semaphore.wait();
				} catch (InterruptedException intex) {
					if (intex instanceof SimulationStoppedException)
						throw (SimulationStoppedException) intex;
				}
			}
			//      xConsole.debug("waking up " + Thread.currentThread());
			th.sleepy = false;
		}
	}



	public void wakeUp(){
		if (semaphore != null)
			synchronized(semaphore) {
				if(sleepy){
					semaphore.notifyAll(); //unlocks the wait & the loop key
				}
			}
	}

	public void forceStop(){
		xConsole.debug("throwing SimulationStoppedException in thread: " + this);
		//    wakeUp();
		stop(new SimulationStoppedException());
		wakeUp();
	}
}











